#include "./display.h"
#include "../device/device.h"
#include "../rtx/rtx_os.h"
#include "../service/device_info.h"

namespace driver {

using namespace service;

utils::Object<Display_t> display;

const uint8_t A = 0x01;
const uint8_t B = 0x02;
const uint8_t C = 0x04;
const uint8_t D = 0x08;
const uint8_t E = 0x10;
const uint8_t F = 0x20;
const uint8_t G = 0x40;

const uint8_t NumList[] = {
    A + B + C + D + E + F,
    B + C,
    A + B + G + E + D,
    A + B + G + C + D,
    F + G + B + C,
    A + F + G + C + D,
    A + F + G + C + D + E,
    A + B + C,
    A + B + C + D + E + F + G,
    A + B + G + F + C + D,
};

// PB13 <=> TX5

Display_t::Display_t() {

    GPIO_InitStruType gpio;
    UART_InitStruType uart;

    gpio.GPIO_Signal = GPIO_Pin_Signal_Digital;
    gpio.GPIO_Func = GPIO_Func_1;
    gpio.GPIO_Direction = GPIO_Dir_Out;
    gpio.GPIO_PUEN = GPIO_PUE_Input_Disable;
    gpio.GPIO_PDEN = GPIO_PDE_Input_Disable;
    gpio.GPIO_OD = GPIO_ODE_Output_Disable;
    gpio.GPIO_DS = GPIO_DS_Output_Strong;
    GPIO_Init(GPIOB, GPIO_Pin_13, &gpio);

    //GPIOB_SetBit(GPIO_Pin_13);

    gpio.GPIO_Func = GPIO_Func_0;
    gpio.GPIO_Direction = GPIO_Dir_In;
    GPIO_Init(GPIOA, GPIO_Pin_0, &gpio);
    GPIOA_SetBit(GPIO_Pin_0);

    uart.UART_StopBits = UART_StopBits_1;
    uart.UART_TxMode = UART_DataMode_8Odd;
    uart.UART_TxPolar =  UART_Polar_Opposite;
    uart.UART_RxMode = UART_DataMode_8Odd;
    uart.UART_RxPolar = UART_Polar_Opposite;
    uart.UART_BaudRate = 19200;
    uart.UART_ClockSet = UART_Clock_1;
    UART_Init(UART5, &uart);   

    UART_TBIMConfig(UART5, UART_TRBIM_Byte);

    UART5_TxEnable();
}

void Display_t::set_price(uint8_t price) {
    if (deviceInfo->price != price) {
        deviceInfo->price = price;
        deviceInfo.save();
    }
    show(Right, price);
}

uint8_t Display_t::price() {
    return deviceInfo->price;
}

void Display_t::show_price(Align_t align) {
    show(align, deviceInfo->price);
}

void Display_t::show(uint8_t h4, uint8_t h3, uint8_t h2, uint8_t h1) {
    write_byte(0x08);
    write_byte(NumList[h4]);
    write_byte(NumList[h3]);
    write_byte(NumList[h2]);
    write_byte(NumList[h1]);
    osDelay(50);
    write_byte(0x18);
    write_byte(0x4F);
    osDelay(50);
}

void Display_t::show(Align_t align, uint8_t val) {
    uint8_t h = (val / 10) % 10;
    uint8_t l = val % 10;
    
    write_byte(0x08);

    if (align == Right) {
        write_byte(0);
        write_byte(0);
        if (h == 0) {
            write_byte(0);
        } else {
            write_byte(NumList[h]);
        }
        write_byte(NumList[l]);
    } else {
        if (h == 0) {
            write_byte(0);
        } else {
            write_byte(NumList[h]);
        }
        write_byte(NumList[l]);
        write_byte(0);
        write_byte(0);
    }

    osDelay(10);
    write_byte(0x18);
    write_byte(0x4F);
    osDelay(10);
}

void Display_t::write_byte(uint8_t byte) {
    
    while(UART_GetFlagStatus(UART5, UART_FLAG_TB) == RESET);
    UART_SendByte(UART5, byte);
}

}

